package com.jia.service.redis;

import com.jia.utils.TimeUtils;
import org.springframework.data.redis.core.BoundSetOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;

import javax.annotation.Resource;
import java.util.Date;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

//@Service
public class OnlineRedisService {
    //    @Autowired
//    private StringRedisTemplate stringRedisTemplate;

//    @Resource(name = "onlineRedisTemplate")
    StringRedisTemplate stringRedisTemplate;

    public void setValue(String key, String value) {
        stringRedisTemplate.boundValueOps(key).set(value);
    }

    public void setValueForExpire(String key, String value, long time, TimeUnit unit) {
        stringRedisTemplate.boundValueOps(key).set(value, time, unit);
    }

    public long incrementForKey(String key) {
        return this.stringRedisTemplate.boundValueOps(key).increment();
    }

    public long incrementForKey(String key, long val) {
        return this.stringRedisTemplate.boundValueOps(key).increment(val);
    }

    public void ZSetOperationsKey(String key, String val, long score) {
        ZSetOperations zSetOperations = stringRedisTemplate.opsForZSet();
        zSetOperations.add(key, val, score);
    }

    public void ZSetIncrementKey(String key, String val, long score) {
        ZSetOperations zSetOperations = stringRedisTemplate.opsForZSet();
        zSetOperations.incrementScore(key, val, score);
    }


    public Set getZSetOperationsKey(String key, long start, long end) {
        ZSetOperations zSetOperations = stringRedisTemplate.opsForZSet();
        Set result = zSetOperations.reverseRangeWithScores(key, start, end);
        return result;
    }


    public void getSetOperationsKey(String key, String value) {
        BoundSetOperations setOperations = stringRedisTemplate.boundSetOps(key);
        setOperations.add(value);
    }


    public void delSetOperationsKey(String key, String value) {
        BoundSetOperations setOperations = stringRedisTemplate.boundSetOps(key);
        setOperations.remove(value);
    }


    public Set querySetOperationsKey(String key) {
        BoundSetOperations setOperations = stringRedisTemplate.boundSetOps(key);
        return setOperations.members();
    }


    public void deleteKey(String key) {
        this.stringRedisTemplate.delete(key);
    }


    /**
     * @param strpattern 模糊语法
     * @prief 根据模糊语法删除KEY符合查询所有记录 eg：User:*
     */
    public void deleteKeys(String strpattern) {
        Set<String> keys = stringRedisTemplate.keys(strpattern);
        this.stringRedisTemplate.delete(keys);
    }

    /**
     * -1 表示永不过期  -2 表示key 不存在  如果返回表示有过期时间 单位是毫秒
     *
     * @param key
     * @return
     */
    public long getTTLForKey(String key) {
        return stringRedisTemplate.boundValueOps(key).getExpire();
    }

    public long addTTLForKey(String key, long ttl) {
        long t = this.getTTLForKey(key);
        if (ttl == 0) {
            return ttl;
        }
        if (t == -2) {
            this.setValueForExpire(key, "1", ttl, TimeUnit.MILLISECONDS);
            return ttl;
        } else {
            if (t == -1) {
                t = 0;
            }
        }

        long tl = ttl + t;
        this.expire(key, tl, TimeUnit.MILLISECONDS);
        return tl;
    }

    /***
     * 自动设置过期时间为 第二天凌晨
     * @param key
     * @param value
     */
    public void setExpireTomorrowForKey(String key, String value) {
        Long cha = TimeUtils.getTomorrow2Today();
        if (cha > 0) {
            stringRedisTemplate.boundValueOps(key).set(value, cha, TimeUnit.MILLISECONDS);
        }
    }

    /***
     * 过期时间 下周一零点
     * @param key
     * @param value
     */
    public void setExpireNextMondayForKey(String key, String value) {
        Long cha = TimeUtils.getNextMonday2Today();
        if (cha > 0) {
            stringRedisTemplate.boundValueOps(key).set(value, cha, TimeUnit.MILLISECONDS);
        }
    }

    /***
     * 自动设置过期时间为 下月1号零点
     * @param key
     * @param value
     */
    public void setExpireNextMonthForKey(String key, String value) {
        Long cha = TimeUtils.getNextMonthBegin2Today();
        if (cha > 0) {
            stringRedisTemplate.boundValueOps(key).set(value, cha, TimeUnit.MILLISECONDS);
        }
    }

    public String getValueForKey(String key) {
        return stringRedisTemplate.boundValueOps(key).get();
    }

    public boolean hasKey(String key) {
        return stringRedisTemplate.hasKey(key);
    }

    public void expireAt(String key, Date date) {
        stringRedisTemplate.expireAt(key, date);
    }

    public void expire(String key, final long timeout, final TimeUnit unit) {
        stringRedisTemplate.expire(key, timeout, unit);
    }

    // 删除过期限制
    public void persist(String key) {
        stringRedisTemplate.persist(key);
    }

    public void setHashValue(String key, Map<String, String> map) {
        stringRedisTemplate.opsForHash().putAll(key, map);
    }


    public String getHashValueForMember(String key, String member) {
        return (String) stringRedisTemplate.boundHashOps(key).get(member);
    }

    public Map<Object, Object> queryHashValueForMember(String key) {
        return stringRedisTemplate.boundHashOps(key).entries();
    }

    public void setHashValueForInnerKey(String key, Object key1, Object value) {
        stringRedisTemplate.boundHashOps(key).put(key1, value);
    }


    public void incrementHashValueForInnerKey(String key, Object key1, long score) {
        stringRedisTemplate.boundHashOps(key).increment(key1, score);
    }

    public Map<String, String> getHashValueForKey(String key) {
        Map map = stringRedisTemplate.opsForHash().entries(key);
        return map;
    }


    public void setCollectionValue(String key, String value) {
        stringRedisTemplate.boundSetOps(key).add(value);
    }


    public boolean IsCollectionMember(String key, String value) {
        boolean flag = stringRedisTemplate.boundSetOps(key).isMember(value);
        return flag;
    }

}
